use crate::{HadesCryptoError, HadesCryptoResult};
use crypto::ed25519;
use rand::Rng;

// 生成公钥私钥的种子
pub fn generate_seed() -> [u8; 32] {
    let mut ret = [0_u8; 32];

    for i in 0..32 {
        let mut r = rand::thread_rng();
        let a = r.gen_range(0_u8, 255_u8);
        ret[i] = a;
    }
    ret
}

// 生成字符串化的私钥和公钥base64 0:私钥 1：公钥
pub fn generate_private_public() -> (String, String) {
    let seed = generate_seed();
    let (private_value, public_value) = ed25519::keypair(&seed);
    let private = base64::encode(private_value);
    let public = base64::encode(public_value);
    (private, public)
}

pub fn signature(message: &str, private_key: &str) -> HadesCryptoResult<String> {
    let private_key = base64::decode(private_key)?;
    let sign = ed25519::signature(message.as_bytes(), &private_key);
    Ok(base64::encode(sign))
}

pub fn verify(message: &str, public_key: &str, signature: &str) -> HadesCryptoResult<()> {
    let public_key = base64::decode(public_key)?;
    let signature = base64::decode(signature)?;
    if ed25519::verify(message.as_bytes(), &public_key, &signature) {
        Ok(())
    } else {
        Err(HadesCryptoError::Verify("verify failed".to_string()))
    }
}

#[cfg(test)]
mod tests {
    use crate::key::{generate_private_public, generate_seed, signature, verify};

    #[test]
    fn test_generate_seed() {
        let seed = generate_seed();
        println!("seed: {:?}", seed);
    }

    #[test]
    fn test_generate_key() {
        let (private, public) = generate_private_public();
        println!("private: {}", private);
        println!("publick: {}", public);
    }

    #[test]
    fn test_sign() {
        let (private, public) = generate_private_public();
        println!("private: {}", private);
        println!("publick: {}", public);
        let sign = signature("hello", &private).unwrap();
        let res = verify("hello", &public, &sign);
        if let Err(e) = res {
            println!("err: {}", e);
        } else {
            println!("success!");
        }
    }
}
